/**************************************************************************************
 * Copyright (C) 2008 EsperTech, Inc. All rights reserved.                            *
 * http://esper.codehaus.org                                                          *
 * http://www.espertech.com                                                           *
 * ---------------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the GPL license       *
 * a copy of which has been included with this distribution in the license.txt file.  *
 **************************************************************************************/
package com.espertech.esper.epl.subquery;

import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.epl.agg.service.AggregationService;
import com.espertech.esper.epl.expression.ExprEvaluator;
import com.espertech.esper.epl.expression.ExprEvaluatorContext;
import com.espertech.esper.view.ViewSupport;

import java.util.Iterator;

/**
 * View handling the insert and remove stream generated by a subselect
 * for application to aggregation state.
 */
public class SubselectAggregatorView extends ViewSupport
{
    private final AggregationService aggregationService;
    private final ExprEvaluator optionalFilterExpr;
    private final ExprEvaluatorContext exprEvaluatorContext;

    /**
     * Ctor.
     * @param aggregationService for aggregating
     * @param optionalFilterExpr for filtering the view-posted events before aggregation
     * @param exprEvaluatorContext expression evaluation context
     */
    public SubselectAggregatorView(AggregationService aggregationService, ExprEvaluator optionalFilterExpr, ExprEvaluatorContext exprEvaluatorContext) {
        this.aggregationService = aggregationService;
        this.optionalFilterExpr = optionalFilterExpr;
        this.exprEvaluatorContext = exprEvaluatorContext;
    }

    public void update(EventBean[] newData, EventBean[] oldData) {
        EventBean[] eventsPerStream = new EventBean[1];

        if (newData != null)
        {
            for (EventBean theEvent : newData)
            {
                eventsPerStream[0] = theEvent;

                boolean isPass = filter(eventsPerStream, true, exprEvaluatorContext);
                if (isPass)
                {
                    aggregationService.applyEnter(eventsPerStream, null, exprEvaluatorContext);
                }
            }
        }

        if (oldData != null)
        {
            for (EventBean theEvent : oldData)
            {
                eventsPerStream[0] = theEvent;
                boolean isPass = filter(eventsPerStream, false, exprEvaluatorContext);
                if (isPass)
                {
                    aggregationService.applyLeave(eventsPerStream, null, exprEvaluatorContext);
                }
            }
        }
    }

    public EventType getEventType() {
        return this.getParent().getEventType();
    }

    public Iterator<EventBean> iterator() {
        return this.getParent().iterator();
    }

    private boolean filter(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
    {
        if (optionalFilterExpr == null)
        {
            return true;
        }

        Boolean result = (Boolean) optionalFilterExpr.evaluate(eventsPerStream, isNewData, exprEvaluatorContext);
        if (result == null)
        {
            return false;
        }
        return result;
    }
}
